from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from django.utils import timezone
from django.db.models import Q, Avg, Count, Max, Min
from django.db import transaction
from datetime import datetime, timedelta
import json

from .models import (
    SystemMetric, MetricData, SystemAlert, HealthCheck,
    PerformanceLog, SystemConfiguration, MonitoringDashboard
)
from .serializers import (
    SystemMetricSerializer, MetricDataSerializer, SystemAlertSerializer,
    HealthCheckSerializer, PerformanceLogSerializer, SystemConfigurationSerializer,
    MonitoringDashboardSerializer, MetricStatisticsSerializer, AlertSummarySerializer
)
from .services import MonitoringService, AlertService, PerformanceAnalyzer


class SystemMetricViewSet(viewsets.ModelViewSet):
    """
    系统指标管理
    """
    queryset = SystemMetric.objects.all()
    serializer_class = SystemMetricSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        queryset = super().get_queryset()
        metric_type = self.request.query_params.get('metric_type')
        is_active = self.request.query_params.get('is_active')
        
        if metric_type:
            queryset = queryset.filter(metric_type=metric_type)
        if is_active is not None:
            queryset = queryset.filter(is_active=is_active.lower() == 'true')
        
        return queryset.order_by('-created_at')
    
    @action(detail=True, methods=['get'])
    def data(self, request, pk=None):
        """
        获取指标数据
        """
        metric = self.get_object()
        
        # 时间范围参数
        start_time = request.query_params.get('start_time')
        end_time = request.query_params.get('end_time')
        hours = request.query_params.get('hours', 24)  # 默认24小时
        
        try:
            hours = int(hours)
        except ValueError:
            hours = 24
        
        # 构建查询条件
        queryset = MetricData.objects.filter(metric=metric)
        
        if start_time and end_time:
            try:
                start_dt = datetime.fromisoformat(start_time.replace('Z', '+00:00'))
                end_dt = datetime.fromisoformat(end_time.replace('Z', '+00:00'))
                queryset = queryset.filter(timestamp__range=[start_dt, end_dt])
            except ValueError:
                return Response({'error': '时间格式错误'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            # 默认查询最近N小时的数据
            end_dt = timezone.now()
            start_dt = end_dt - timedelta(hours=hours)
            queryset = queryset.filter(timestamp__range=[start_dt, end_dt])
        
        # 数据聚合
        aggregation = request.query_params.get('aggregation', 'raw')
        if aggregation == 'hourly':
            # 按小时聚合
            data = queryset.extra({
                'hour': "date_trunc('hour', timestamp)"
            }).values('hour').annotate(
                avg_value=Avg('value'),
                max_value=Max('value'),
                min_value=Min('value'),
                count=Count('id')
            ).order_by('hour')
        elif aggregation == 'daily':
            # 按天聚合
            data = queryset.extra({
                'day': "date_trunc('day', timestamp)"
            }).values('day').annotate(
                avg_value=Avg('value'),
                max_value=Max('value'),
                min_value=Min('value'),
                count=Count('id')
            ).order_by('day')
        else:
            # 原始数据
            data = MetricDataSerializer(queryset.order_by('-timestamp')[:1000], many=True).data
        
        return Response({
            'metric': SystemMetricSerializer(metric).data,
            'data': data,
            'aggregation': aggregation
        })
    
    @action(detail=True, methods=['get'])
    def statistics(self, request, pk=None):
        """
        获取指标统计信息
        """
        metric = self.get_object()
        hours = int(request.query_params.get('hours', 24))
        
        end_time = timezone.now()
        start_time = end_time - timedelta(hours=hours)
        
        stats = MetricData.objects.filter(
            metric=metric,
            timestamp__range=[start_time, end_time]
        ).aggregate(
            avg_value=Avg('value'),
            max_value=Max('value'),
            min_value=Min('value'),
            count=Count('id')
        )
        
        # 计算阈值违规次数
        warning_violations = 0
        critical_violations = 0
        
        if metric.warning_threshold is not None:
            warning_violations = MetricData.objects.filter(
                metric=metric,
                timestamp__range=[start_time, end_time],
                value__gte=metric.warning_threshold
            ).count()
        
        if metric.critical_threshold is not None:
            critical_violations = MetricData.objects.filter(
                metric=metric,
                timestamp__range=[start_time, end_time],
                value__gte=metric.critical_threshold
            ).count()
        
        stats.update({
            'warning_violations': warning_violations,
            'critical_violations': critical_violations,
            'time_range': {
                'start': start_time,
                'end': end_time,
                'hours': hours
            }
        })
        
        return Response(stats)
    
    @action(detail=False, methods=['post'])
    def collect_data(self, request):
        """
        批量收集指标数据
        """
        data = request.data
        if not isinstance(data, list):
            data = [data]
        
        created_count = 0
        errors = []
        
        for item in data:
            try:
                metric_name = item.get('metric_name')
                metric_type = item.get('metric_type')
                value = item.get('value')
                timestamp = item.get('timestamp')
                tags = item.get('tags', {})
                
                if not all([metric_name, metric_type, value is not None]):
                    errors.append({'item': item, 'error': '缺少必要字段'})
                    continue
                
                # 查找或创建指标
                metric, created = SystemMetric.objects.get_or_create(
                    name=metric_name,
                    metric_type=metric_type,
                    defaults={
                        'unit': item.get('unit', ''),
                        'description': item.get('description', '')
                    }
                )
                
                # 创建指标数据
                if timestamp:
                    timestamp = datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
                else:
                    timestamp = timezone.now()
                
                MetricData.objects.create(
                    metric=metric,
                    value=float(value),
                    timestamp=timestamp,
                    tags=tags
                )
                
                created_count += 1
                
            except Exception as e:
                errors.append({'item': item, 'error': str(e)})
        
        return Response({
            'created_count': created_count,
            'errors': errors
        })


class MetricDataViewSet(viewsets.ReadOnlyModelViewSet):
    """
    指标数据查询（只读）
    """
    queryset = MetricData.objects.all()
    serializer_class = MetricDataSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        queryset = super().get_queryset()
        
        # 过滤参数
        metric_id = self.request.query_params.get('metric_id')
        metric_name = self.request.query_params.get('metric_name')
        start_time = self.request.query_params.get('start_time')
        end_time = self.request.query_params.get('end_time')
        
        if metric_id:
            queryset = queryset.filter(metric_id=metric_id)
        if metric_name:
            queryset = queryset.filter(metric__name=metric_name)
        
        if start_time and end_time:
            try:
                start_dt = datetime.fromisoformat(start_time.replace('Z', '+00:00'))
                end_dt = datetime.fromisoformat(end_time.replace('Z', '+00:00'))
                queryset = queryset.filter(timestamp__range=[start_dt, end_dt])
            except ValueError:
                pass
        
        return queryset.order_by('-timestamp')


class SystemAlertViewSet(viewsets.ModelViewSet):
    """
    系统告警管理
    """
    queryset = SystemAlert.objects.all()
    serializer_class = SystemAlertSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        queryset = super().get_queryset()
        
        # 过滤参数
        status_filter = self.request.query_params.get('status')
        alert_level = self.request.query_params.get('alert_level')
        metric_id = self.request.query_params.get('metric_id')
        
        if status_filter:
            queryset = queryset.filter(status=status_filter)
        if alert_level:
            queryset = queryset.filter(alert_level=alert_level)
        if metric_id:
            queryset = queryset.filter(metric_id=metric_id)
        
        return queryset.order_by('-triggered_at')
    
    @action(detail=True, methods=['post'])
    def acknowledge(self, request, pk=None):
        """
        确认告警
        """
        alert = self.get_object()
        
        if alert.status != 'active':
            return Response(
                {'error': '只能确认活跃状态的告警'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        alert.acknowledge(request.user)
        
        return Response({
            'message': '告警已确认',
            'alert': SystemAlertSerializer(alert).data
        })
    
    @action(detail=True, methods=['post'])
    def resolve(self, request, pk=None):
        """
        解决告警
        """
        alert = self.get_object()
        
        if alert.status == 'resolved':
            return Response(
                {'error': '告警已经是解决状态'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        alert.resolve(request.user)
        
        return Response({
            'message': '告警已解决',
            'alert': SystemAlertSerializer(alert).data
        })
    
    @action(detail=True, methods=['post'])
    def suppress(self, request, pk=None):
        """
        抑制告警
        """
        alert = self.get_object()
        alert.suppress()
        
        return Response({
            'message': '告警已抑制',
            'alert': SystemAlertSerializer(alert).data
        })
    
    @action(detail=False, methods=['get'])
    def summary(self, request):
        """
        告警摘要统计
        """
        # 统计各状态告警数量
        status_stats = SystemAlert.objects.values('status').annotate(
            count=Count('id')
        ).order_by('status')
        
        # 统计各级别告警数量
        level_stats = SystemAlert.objects.values('alert_level').annotate(
            count=Count('id')
        ).order_by('alert_level')
        
        # 最近24小时新增告警
        last_24h = timezone.now() - timedelta(hours=24)
        recent_alerts = SystemAlert.objects.filter(
            triggered_at__gte=last_24h
        ).count()
        
        # 活跃告警
        active_alerts = SystemAlert.objects.filter(status='active').count()
        
        return Response({
            'status_stats': list(status_stats),
            'level_stats': list(level_stats),
            'recent_alerts_24h': recent_alerts,
            'active_alerts': active_alerts
        })


class HealthCheckViewSet(viewsets.ModelViewSet):
    """
    健康检查管理
    """
    queryset = HealthCheck.objects.all()
    serializer_class = HealthCheckSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        queryset = super().get_queryset()
        
        check_type = self.request.query_params.get('check_type')
        status_filter = self.request.query_params.get('status')
        is_active = self.request.query_params.get('is_active')
        
        if check_type:
            queryset = queryset.filter(check_type=check_type)
        if status_filter:
            queryset = queryset.filter(status=status_filter)
        if is_active is not None:
            queryset = queryset.filter(is_active=is_active.lower() == 'true')
        
        return queryset.order_by('-last_check_time')
    
    @action(detail=True, methods=['post'])
    def execute_check(self, request, pk=None):
        """
        执行健康检查
        """
        health_check = self.get_object()
        
        try:
            # 使用监控服务执行检查
            monitoring_service = MonitoringService()
            result = monitoring_service.execute_health_check(health_check)
            
            if result['success']:
                health_check.record_success()
                message = '健康检查通过'
            else:
                health_check.record_failure(result['error'])
                message = f'健康检查失败: {result["error"]}'
            
            return Response({
                'message': message,
                'result': result,
                'health_check': HealthCheckSerializer(health_check).data
            })
            
        except Exception as e:
            health_check.record_failure(str(e))
            return Response(
                {'error': f'执行健康检查时发生错误: {str(e)}'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
    
    @action(detail=False, methods=['post'])
    def execute_all(self, request):
        """
        执行所有活跃的健康检查
        """
        active_checks = HealthCheck.objects.filter(is_active=True)
        results = []
        
        monitoring_service = MonitoringService()
        
        for health_check in active_checks:
            try:
                result = monitoring_service.execute_health_check(health_check)
                
                if result['success']:
                    health_check.record_success()
                else:
                    health_check.record_failure(result['error'])
                
                results.append({
                    'health_check_id': health_check.id,
                    'name': health_check.name,
                    'success': result['success'],
                    'error': result.get('error')
                })
                
            except Exception as e:
                health_check.record_failure(str(e))
                results.append({
                    'health_check_id': health_check.id,
                    'name': health_check.name,
                    'success': False,
                    'error': str(e)
                })
        
        return Response({
            'message': f'执行了 {len(active_checks)} 个健康检查',
            'results': results
        })
    
    @action(detail=False, methods=['get'])
    def status_overview(self, request):
        """
        健康检查状态概览
        """
        # 统计各状态数量
        status_stats = HealthCheck.objects.filter(is_active=True).values('status').annotate(
            count=Count('id')
        ).order_by('status')
        
        # 计算总体健康度
        total_checks = HealthCheck.objects.filter(is_active=True).count()
        healthy_checks = HealthCheck.objects.filter(is_active=True, status='healthy').count()
        
        health_percentage = (healthy_checks / total_checks * 100) if total_checks > 0 else 0
        
        return Response({
            'status_stats': list(status_stats),
            'total_checks': total_checks,
            'healthy_checks': healthy_checks,
            'health_percentage': round(health_percentage, 2)
        })


class PerformanceLogViewSet(viewsets.ReadOnlyModelViewSet):
    """
    性能日志查询（只读）
    """
    queryset = PerformanceLog.objects.all()
    serializer_class = PerformanceLogSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        queryset = super().get_queryset()
        
        # 过滤参数
        log_type = self.request.query_params.get('log_type')
        operation = self.request.query_params.get('operation')
        user_id = self.request.query_params.get('user_id')
        success = self.request.query_params.get('success')
        start_time = self.request.query_params.get('start_time')
        end_time = self.request.query_params.get('end_time')
        
        if log_type:
            queryset = queryset.filter(log_type=log_type)
        if operation:
            queryset = queryset.filter(operation__icontains=operation)
        if user_id:
            queryset = queryset.filter(user_id=user_id)
        if success is not None:
            queryset = queryset.filter(success=success.lower() == 'true')
        
        if start_time and end_time:
            try:
                start_dt = datetime.fromisoformat(start_time.replace('Z', '+00:00'))
                end_dt = datetime.fromisoformat(end_time.replace('Z', '+00:00'))
                queryset = queryset.filter(timestamp__range=[start_dt, end_dt])
            except ValueError:
                pass
        
        return queryset.order_by('-timestamp')
    
    @action(detail=False, methods=['get'])
    def performance_stats(self, request):
        """
        性能统计分析
        """
        hours = int(request.query_params.get('hours', 24))
        log_type = request.query_params.get('log_type')
        
        end_time = timezone.now()
        start_time = end_time - timedelta(hours=hours)
        
        queryset = PerformanceLog.objects.filter(
            timestamp__range=[start_time, end_time]
        )
        
        if log_type:
            queryset = queryset.filter(log_type=log_type)
        
        # 性能统计
        stats = queryset.aggregate(
            avg_duration=Avg('duration_ms'),
            max_duration=Max('duration_ms'),
            min_duration=Min('duration_ms'),
            total_requests=Count('id'),
            success_count=Count('id', filter=Q(success=True)),
            error_count=Count('id', filter=Q(success=False))
        )
        
        # 计算成功率
        success_rate = 0
        if stats['total_requests'] > 0:
            success_rate = (stats['success_count'] / stats['total_requests']) * 100
        
        stats['success_rate'] = round(success_rate, 2)
        
        # 按操作类型统计
        operation_stats = queryset.values('log_type').annotate(
            avg_duration=Avg('duration_ms'),
            count=Count('id')
        ).order_by('-avg_duration')
        
        return Response({
            'overall_stats': stats,
            'operation_stats': list(operation_stats),
            'time_range': {
                'start': start_time,
                'end': end_time,
                'hours': hours
            }
        })


class SystemConfigurationViewSet(viewsets.ModelViewSet):
    """
    系统配置管理
    """
    queryset = SystemConfiguration.objects.all()
    serializer_class = SystemConfigurationSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        queryset = super().get_queryset()
        
        config_type = self.request.query_params.get('config_type')
        is_active = self.request.query_params.get('is_active')
        
        if config_type:
            queryset = queryset.filter(config_type=config_type)
        if is_active is not None:
            queryset = queryset.filter(is_active=is_active.lower() == 'true')
        
        return queryset.order_by('config_type', 'name')
    
    def perform_update(self, serializer):
        """
        更新配置时记录修改人
        """
        serializer.save(last_modified_by=self.request.user)
    
    @action(detail=False, methods=['get'])
    def by_type(self, request):
        """
        按类型获取配置
        """
        config_type = request.query_params.get('type')
        if not config_type:
            return Response(
                {'error': '请指定配置类型'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        configs = SystemConfiguration.objects.filter(
            config_type=config_type,
            is_active=True
        )
        
        serializer = SystemConfigurationSerializer(configs, many=True)
        return Response(serializer.data)


class MonitoringDashboardViewSet(viewsets.ModelViewSet):
    """
    监控仪表板管理
    """
    queryset = MonitoringDashboard.objects.all()
    serializer_class = MonitoringDashboardSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        queryset = super().get_queryset()
        user = self.request.user
        
        # 只返回用户可以访问的仪表板
        queryset = queryset.filter(
            Q(is_public=True) |
            Q(created_by=user) |
            Q(allowed_users=user)
        ).distinct()
        
        return queryset.filter(is_active=True).order_by('-created_at')
    
    def perform_create(self, serializer):
        """
        创建仪表板时设置创建者
        """
        serializer.save(created_by=self.request.user)
    
    @action(detail=True, methods=['get'])
    def data(self, request, pk=None):
        """
        获取仪表板数据
        """
        dashboard = self.get_object()
        
        # 检查访问权限
        if not dashboard.can_access(request.user):
            return Response(
                {'error': '没有访问权限'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # 获取仪表板组件数据
        widget_data = []
        
        for widget in dashboard.widgets:
            try:
                widget_type = widget.get('type')
                widget_config = widget.get('config', {})
                
                if widget_type == 'metric_chart':
                    # 指标图表数据
                    metric_id = widget_config.get('metric_id')
                    if metric_id:
                        metric = SystemMetric.objects.get(id=metric_id)
                        hours = widget_config.get('hours', 24)
                        
                        end_time = timezone.now()
                        start_time = end_time - timedelta(hours=hours)
                        
                        data = MetricData.objects.filter(
                            metric=metric,
                            timestamp__range=[start_time, end_time]
                        ).order_by('timestamp').values('timestamp', 'value')
                        
                        widget_data.append({
                            'widget_id': widget.get('id'),
                            'type': widget_type,
                            'data': list(data)
                        })
                
                elif widget_type == 'alert_summary':
                    # 告警摘要数据
                    active_alerts = SystemAlert.objects.filter(status='active').count()
                    recent_alerts = SystemAlert.objects.filter(
                        triggered_at__gte=timezone.now() - timedelta(hours=24)
                    ).count()
                    
                    widget_data.append({
                        'widget_id': widget.get('id'),
                        'type': widget_type,
                        'data': {
                            'active_alerts': active_alerts,
                            'recent_alerts': recent_alerts
                        }
                    })
                
                elif widget_type == 'health_status':
                    # 健康状态数据
                    total_checks = HealthCheck.objects.filter(is_active=True).count()
                    healthy_checks = HealthCheck.objects.filter(
                        is_active=True, status='healthy'
                    ).count()
                    
                    widget_data.append({
                        'widget_id': widget.get('id'),
                        'type': widget_type,
                        'data': {
                            'total_checks': total_checks,
                            'healthy_checks': healthy_checks,
                            'health_percentage': (healthy_checks / total_checks * 100) if total_checks > 0 else 0
                        }
                    })
                
            except Exception as e:
                widget_data.append({
                    'widget_id': widget.get('id'),
                    'type': widget_type,
                    'error': str(e)
                })
        
        return Response({
            'dashboard': MonitoringDashboardSerializer(dashboard).data,
            'widget_data': widget_data,
            'last_updated': timezone.now()
        })
    
    @action(detail=True, methods=['post'])
    def share(self, request, pk=None):
        """
        分享仪表板
        """
        dashboard = self.get_object()
        
        # 检查是否是创建者
        if dashboard.created_by != request.user:
            return Response(
                {'error': '只有创建者可以分享仪表板'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        user_ids = request.data.get('user_ids', [])
        is_public = request.data.get('is_public', False)
        
        # 设置公开状态
        dashboard.is_public = is_public
        
        # 添加允许访问的用户
        if user_ids:
            from django.contrib.auth import get_user_model
            User = get_user_model()
            users = User.objects.filter(id__in=user_ids)
            dashboard.allowed_users.set(users)
        
        dashboard.save()
        
        return Response({
            'message': '仪表板分享设置已更新',
            'dashboard': MonitoringDashboardSerializer(dashboard).data
        })


class MonitoringOverviewView(viewsets.ViewSet):
    """
    监控概览视图
    """
    permission_classes = [IsAuthenticated]
    
    @action(detail=False, methods=['get'])
    def system_overview(self, request):
        """
        系统监控概览
        """
        # 系统指标概览
        total_metrics = SystemMetric.objects.filter(is_active=True).count()
        
        # 告警概览
        active_alerts = SystemAlert.objects.filter(status='active').count()
        critical_alerts = SystemAlert.objects.filter(
            status='active', alert_level='critical'
        ).count()
        
        # 健康检查概览
        total_health_checks = HealthCheck.objects.filter(is_active=True).count()
        healthy_checks = HealthCheck.objects.filter(
            is_active=True, status='healthy'
        ).count()
        
        # 性能概览（最近1小时）
        one_hour_ago = timezone.now() - timedelta(hours=1)
        recent_performance = PerformanceLog.objects.filter(
            timestamp__gte=one_hour_ago
        ).aggregate(
            avg_duration=Avg('duration_ms'),
            total_requests=Count('id'),
            error_count=Count('id', filter=Q(success=False))
        )
        
        # 计算错误率
        error_rate = 0
        if recent_performance['total_requests'] and recent_performance['total_requests'] > 0:
            error_rate = (recent_performance['error_count'] / recent_performance['total_requests']) * 100
        
        return Response({
            'metrics': {
                'total_active': total_metrics
            },
            'alerts': {
                'active_total': active_alerts,
                'critical_count': critical_alerts
            },
            'health_checks': {
                'total': total_health_checks,
                'healthy': healthy_checks,
                'health_percentage': (healthy_checks / total_health_checks * 100) if total_health_checks > 0 else 0
            },
            'performance': {
                'avg_response_time': recent_performance['avg_duration'] or 0,
                'total_requests_1h': recent_performance['total_requests'] or 0,
                'error_rate_1h': round(error_rate, 2)
            },
            'timestamp': timezone.now()
        })